﻿Imports DotNetNuke
Imports DotNetNuke.Services.Localization
Imports DotNetNuke.Services.Search
Imports DotNetNuke.Services.Exceptions
Imports DotNetNuke.Common.Globals
Imports DotNetNuke.Common.Utilities.DataCache

Imports DotNetNuke.UI.Utilities


Namespace effority.UserDirectory

    Partial Class View
        Inherits effority.UserDirectory.Base
        Implements DotNetNuke.UI.Utilities.IClientAPICallbackEventHandler

#Region " Private Members "

        Private searchString As String

        'Private agentType As Enums.ClientAgentType = Enums.ClientAgentType.Browser

#End Region

#Region " Public Methods "

        Public Function DisplayEmail(ByVal Email As String) As String

            Return DotNetNuke.Common.Utilities.HtmlUtils.FormatEmail(Email)

        End Function


#End Region

#Region " Public Properties "

        ' Paging Settings
        Public ReadOnly Property paging() As Int32
            Get
                If Settings("paging") = "" Then
                    Return 20
                Else
                    Return CInt(Settings("paging"))
                End If
            End Get
        End Property

        Public ReadOnly Property HtmlNoResults() As String
            Get
                Return "<span class='Normal'>" & Localization.GetString("lblNoResults", Me.LocalResourceFile) & "</span>"
            End Get
        End Property

#End Region

#Region " Event Handlers "

        Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

            Try

                Me.RegisterJSFunction()

                If Not IsPostBack Then

                    If Not Request.Params("searchString") Is Nothing Then

                        searchString = CStr(Request.Params("searchString"))
                        searchText.Text = searchString

                    End If

                    If Not Request.Params("Detail") Is Nothing AndAlso CStr(Request.Params("Detail")).ToLower = "true" Then

                        panOverview.Visible = False
                        panDetail.Visible = True

                        ShowDetail(CInt(Request.Params("UserId")))

                    Else

                        panOverview.Visible = True
                        panDetail.Visible = False

                    End If

                    If Me.ShowProfilesToSearchSettings() Then

                        Dim columns As String

                        For i As Int32 = 0 To Me.ProfilesPropertyCollectionToSearch.Count - 1

                            columns &= Me.ProfilesPropertyCollectionToSearch(i).PropertyName

                            If Not i = Me.ProfilesPropertyCollectionToSearch.Count - 1 Then
                                columns &= ", "
                            End If

                        Next

                        lblSettings.Text = String.Format("({0} {1})", DotNetNuke.Services.Localization.Localization.GetString("SearchingIn", Me.LocalResourceFile), columns)
                        lblSettings.Visible = True

                    Else

                        lblSettings.Visible = False

                    End If

                    panGui.Visible = Not Me.DisableSearch

                    Dim dv As DataView = Me.GetUserTable(False)

                    Try

                        dv.RowFilter = Me.BuildSearchExpression(searchString)

                    Catch ex As Exception

                        ProcessModuleLoadException(Me, New Exception("Forced search expression error. Please check the module settings!"))

                    End Try

                    If (Me.SearchStartMode = Enums.SearchStartMode.ShowAllRecords) _
                     Or (Not String.IsNullOrEmpty(searchString)) Then

                        HtmlAnker.InnerHtml = Me.BuildHtmlTable(dv, 1)

                    End If

                End If

                If ClientAPI.BrowserSupportsFunctionality(ClientAPI.ClientFunctionality.XMLHTTP) _
                AndAlso ClientAPI.BrowserSupportsFunctionality(ClientAPI.ClientFunctionality.XML) Then

                    ClientAPI.RegisterClientReference(Me.Page, ClientAPI.ClientNamespaceReferences.dnn_xml)
                    ClientAPI.RegisterClientReference(Me.Page, ClientAPI.ClientNamespaceReferences.dnn_xmlhttp)

                    Me.searchText.Attributes.Add("onkeyup", "SendToUD(1)")

                End If

            Catch exc As Exception

                ProcessModuleLoadException(Me, exc)

            End Try

        End Sub

#End Region

#Region " Private Methods "

        Private Sub RegisterJSFunction()

            Dim script As New System.Text.StringBuilder

            With script

                .Append("<script language=""javascript"">" & vbCrLf)
                .Append("function SendToUD(page) {" & vbCrLf)

                .Append(ClientAPI.GetCallbackEventReference(Me, "'1|1|' + dnn.dom.getById('" & Me.searchText.UniqueID.Replace("$", "_") & "').value + '|' + page + '|'", "successFunc", "this", "errorFunc") & vbCrLf)

                .Append("}" & vbCrLf)

                .Append("function successFunc(result, ctx) {" & vbCrLf)
                .Append("dnn.dom.getById('" & HtmlAnker.UniqueID.Replace("$", "_") & "').innerHTML = result }" & vbCrLf)

                .Append("function errorFunc(result, ctx) {" & vbCrLf)
                .Append("}" & vbCrLf)

                .Append("function Sort(column) {" & vbCrLf)

                .Append(ClientAPI.GetCallbackEventReference(Me, "'2|1|'+ dnn.dom.getById('" & Me.searchText.UniqueID.Replace("$", "_") & "').value + '||' + column", "successSort", "this", "errorSort") & vbCrLf)

                .Append("}" & vbCrLf)

                .Append("function successSort(result, ctx) {" & vbCrLf)

                .Append("dnn.dom.getById('" & HtmlAnker.UniqueID.Replace("$", "_") & "').innerHTML = result }" & vbCrLf)

                .Append("function errorSort(result, ctx) {" & vbCrLf)
                .Append("}" & vbCrLf)

                .Append("</script>" & vbCrLf)

            End With

            Page.RegisterClientScriptBlock("SendToUD", script.ToString)

        End Sub

        Private Function GetUserTable(ByVal FromCache As Boolean) As DataView

            Dim UserTable As DataTable

            If FromCache Then
                UserTable = CType(DotNetNuke.Services.Cache.CachingProvider.Instance.GetItem(Me.USERTABLE_MODULE_CACHE), DataTable)
            End If

            If UserTable Is Nothing Then

                UserTable = New System.Data.DataTable

                UserTable.BeginLoadData()

                Dim profilePropertyCollection As DotNetNuke.Entities.Profile.ProfilePropertyDefinitionCollection = _
                           DotNetNuke.Entities.Profile.ProfileController.GetPropertyDefinitionsByPortal(PortalId)

                ' load users 
                Dim UserListe As Generic.List(Of effority.UserDirectory.UserIdAndUserName)

                UserListe = Me.GetUsersList()

                ' load profile data 

                Dim userProfileDic As Generic.Dictionary(Of Integer, Generic.Dictionary(Of Integer, String))

                userProfileDic = effority.UserDirectory.Controller.GetUserProfileDic(Me.ProfilesPropertiesToLoad, PortalId)

                UserTable.Columns.Add(effority.UserDirectory.Consts.USERID_COLUMN, GetType(Integer))

                ' build dataTable
                For Each info As DotNetNuke.Entities.Profile.ProfilePropertyDefinition In Me.ProfilesPropertiesToLoad

                    UserTable.Columns.Add(Me.CleanColumnName(info.PropertyName))

                Next

                For Each user As effority.UserDirectory.UserIdAndUserName In UserListe

                    Dim workrow As System.Data.DataRow = UserTable.NewRow()

                    Dim profileForThisUser As Generic.Dictionary(Of Integer, String)

                    workrow(effority.UserDirectory.Consts.USERID_COLUMN) = user.UserId

                    If userProfileDic.TryGetValue(user.UserId, profileForThisUser) Then

                        For Each info As DotNetNuke.Entities.Profile.ProfilePropertyDefinition In Me.ProfilesPropertiesToLoad

                            Dim value As String = String.Empty

                            If info.PropertyDefinitionId = Consts.USERNAME_PROFILE_ID Then
                                value = user.UserName
                            ElseIf info.PropertyDefinitionId = Consts.EMAIL_PROFILE_ID Then
                                value = user.Email
                            ElseIf info.PropertyDefinitionId = Consts.DISPLAYNAME_PROFILE_ID Then
                                value = user.DisplayName
                            Else
                                If profileForThisUser.TryGetValue(info.PropertyDefinitionId, Nothing) Then
                                    value = profileForThisUser(info.PropertyDefinitionId)
                                Else
                                    If Not String.IsNullOrEmpty(info.DefaultValue) Then
                                        value = info.DefaultValue
                                    End If
                                End If
                            End If

                            If HtmlDecodeDic.TryGetValue(info.PropertyDefinitionId, Nothing) Then

                                If HtmlDecodeDic(info.PropertyDefinitionId) Then

                                    value = Server.HtmlDecode(value)

                                End If

                            End If

                            workrow(CleanColumnName(info.PropertyName)) = value

                        Next

                    End If

                    UserTable.Rows.Add(workrow)

                Next

                UserTable.EndLoadData()

                DotNetNuke.Services.Cache.CachingProvider.Instance.Insert(Me.USERTABLE_MODULE_CACHE, UserTable, False)

            End If

            Dim dv As DataView = UserTable.DefaultView

            dv.Sort = Me.DefaultSortExpression

            Return dv

        End Function

        Private Function GetUsersList() As Generic.List(Of effority.UserDirectory.UserIdAndUserName)

            Dim liste As Generic.List(Of effority.UserDirectory.UserIdAndUserName)

            liste = effority.UserDirectory.Controller.GetUsersInRoles(Me.RolesConfiguration, Me.IgnoreEffectiveExpireDate)

            Return liste

        End Function

        Private Sub ShowDetail(ByVal uId As Int32)

            Dim user As UserInfo = UserController.GetUser(PortalId, uId, True)

            Dim sb As New StringBuilder

            Dim info As New effority.UserDirectory.DetailInfo(user)

            Dim searchString As String = CStr(Request.Params("searchstring"))

            'Dim template As String = Me.detailsTemplate.Replace("[", "[User:")

            sb.Append(info.Replace(Me.detailsTemplate))

            Dim returnURL As String = DotNetNuke.Common.NavigateURL()

            If Not String.IsNullOrEmpty(Me.Session(Me.SESSION_LASTSEARCH)) Then

                returnURL &= "?searchString=" & searchString

            End If

            sb.Append("<div align='center'><a class='NormalBold' href='" & returnURL & "' target='_self'>" & DotNetNuke.Services.Localization.Localization.GetString("Back", Me.LocalResourceFile) & "</a></div>")

            lblDetail.Text = sb.ToString()

        End Sub

#End Region

#Region " Client API "

        Public Function RaiseClientAPICallbackEvent(ByVal eventArgument As String) As String Implements DotNetNuke.UI.Utilities.IClientAPICallbackEventHandler.RaiseClientAPICallbackEvent

            ' Zustand der GUI ermitteln 

            Dim strArray As String() = eventArgument.Split("|")

            ' param 0 = CallBackMode; Search or sort
            ' param 1 = SearchMode; fix or custom ; ausgestorben
            ' param 2 = search expression  
            ' param 3 = page
            ' param 4 = sortColumn

            Dim callBackMode As effority.UserDirectory.Enums.CallBackMode = CType(strArray(0), effority.UserDirectory.Enums.CallBackMode)
            Dim searchMode As effority.UserDirectory.Enums.SearchMode = CType(strArray(1), effority.UserDirectory.Enums.SearchMode)

            Dim searchExpression As String

            Dim searchString As String = strArray(2)

            searchExpression = Me.BuildSearchExpression(searchString)

            Dim dv As DataView = Me.GetUserTable(True)

            dv.RowFilter = searchExpression

            Dim page As Int32

            If Not String.IsNullOrEmpty(strArray(3)) Then
                page = CInt(strArray(3))
                Session(SESSION_PAGE) = CStr(page)
            Else
                If Not Session(SESSION_PAGE) Is Nothing Then
                    page = CInt(Session(SESSION_PAGE))
                Else
                    page = 1
                End If
            End If

            If callBackMode = effority.UserDirectory.Enums.CallBackMode.sort Then

                Dim sortColumn As String = CStr(strArray(4))

                If CStr(Session(SESSION_SORT_EXPRESSION)) = sortColumn & " ASC" Then
                    Session(SESSION_SORT_EXPRESSION) = sortColumn & " DESC"
                Else
                    Session(SESSION_SORT_EXPRESSION) = sortColumn & " ASC"
                End If

                'Else

                '    If Session(SESSION_SORT_EXPRESSION) Is Nothing OrElse _
                '    String.IsNullOrEmpty(Session(SESSION_SORT_EXPRESSION)) Then

                '        Session(SESSION_SORT_EXPRESSION) = Me.DefaultSortExpression

                '    End If

            End If

            If Not Session(SESSION_SORT_EXPRESSION) Is Nothing Then

                dv.Sort = CStr(Session(SESSION_SORT_EXPRESSION))

            Else

                'If dv.Table.Columns.Count > 0 Then

                '    dv.Sort = dv.Table.Columns(0).ColumnName & " ASC"

                'End If

                dv.Sort = Me.DefaultSortExpression

            End If

            If searchString.Length >= Me.MinChar Or Me.SearchStartMode = Enums.SearchStartMode.ShowAllRecords Then

                Return Me.BuildHtmlTableBrowser(dv, page)

            Else

                Return "<span class='Normal'>No Results</span>"

            End If

        End Function

        Private Function BuildHtmlTable(ByVal dv As DataView, ByVal selPage As Int32) As String

            Dim result As String = String.Empty

            Dim agentType As Enums.ClientAgentType = Enums.ClientAgentType.Browser

            If Utils.AnalyseClientAgent(Me.Request.UserAgent) = Enums.ClientAgentType.Browser Then
                result = BuildHtmlTableBrowser(dv, selPage)
            Else
                result = BuildHtmlTableSearchBot(dv)
            End If

            Return result

        End Function

        Private Function BuildHtmlTableBrowser(ByVal dv As DataView, ByVal selPage As Int32) As String

            Dim CssHead As String = "NormalBold"
            Dim CssBody As String = "Normal"

            Try

                If dv Is Nothing OrElse dv.Count = 0 Then

                    Return Me.HtmlNoResults

                Else

                    Dim count As Int32 = dv.Count

                    Dim pages As Int32

                    If ((count Mod Me.paging) <= (Me.paging / 2)) And (count Mod Me.paging <> 0) Then
                        'wird aufgerundet

                        pages = count / Me.paging
                        pages = pages + 1

                    Else

                        pages = count / Me.paging

                    End If

                    Dim sb As New System.Text.StringBuilder

                    sb.Append("<table cellspacing='2' cellpadding='2'>")

                    If Me.DisplayMode = Enums.DisplayMode.Grid Then

                        sb.Append("<tr>")

                        For Each profileProperty As DotNetNuke.Entities.Profile.ProfilePropertyDefinition In Me.ProfilesPropertyCollectionToShow

                            Dim tempName As String = Me.ProfilePropertyNamesLocalDic(profileProperty.PropertyName)

                            sb.Append(String.Format("<td nowrap style='cursor:pointer' onclick='Sort(""{0}"")' class='{1}'>{2}</td>", CleanColumnName(profileProperty.PropertyName), CssHead, tempName))

                        Next

                        sb.Append("</tr>")

                    ElseIf Me.DisplayMode = Enums.DisplayMode.Template Then

                        Dim info As New effority.UserDirectory.ProfilePropertyLocalization(Me.ProfilePropertyNamesLocalDic)

                        sb.Append(info.Replace(Me.DisplayHeadTemplate))

                    End If

                    For x As Int32 = 1 To pages

                        If x = selPage Then

                            For y As Int32 = 1 To Me.paging

                                ' page kommt vom client
                                If dv.Count > (((x - 1) * Me.paging) + (y - 1)) Then

                                    Dim z As Int32 = (((x - 1) * Me.paging) + (y - 1))

                                    If Me.DisplayMode = Enums.DisplayMode.Grid Then

                                        sb.Append("<tr>")

                                        For Each profileProperty As DotNetNuke.Entities.Profile.ProfilePropertyDefinition In Me.ProfilesPropertyCollectionToShow

                                            Dim mode As effority.UserDirectory.Enums.RenderMode = Enums.RenderMode.Text

                                            If Me.DisplayEmailAsMailTo AndAlso profileProperty.PropertyDefinitionId = effority.UserDirectory.Consts.EMAIL_PROFILE_ID Then
                                                mode = effority.UserDirectory.Enums.RenderMode.EmailMailTo
                                            End If

                                            ' Der ProfileLink sticht den EmailLink aus
                                            If (Me.EnableProfileLink AndAlso profileProperty.PropertyDefinitionId = Me.ProfileLinkColumn) Then
                                                mode = effority.UserDirectory.Enums.RenderMode.ProfileLink
                                            End If

                                            If (Me.EnablevCardLink AndAlso profileProperty.PropertyDefinitionId = Me.vCardLinkColumn) Then
                                                mode = effority.UserDirectory.Enums.RenderMode.vCardLink
                                            End If

                                            If (Me.detailsLinkEnable AndAlso profileProperty.PropertyDefinitionId = Me.detailsLinkColumn) Then
                                                mode = effority.UserDirectory.Enums.RenderMode.detailsView
                                            End If

                                            If (Me.TabLinkEnable AndAlso profileProperty.PropertyDefinitionId = Me.TabLinkColumn) Then
                                                mode = effority.UserDirectory.Enums.RenderMode.tabLink
                                            End If

                                            ' Profilewert bei Bedarf kürzen

                                            Dim value As String = dv(z).Item(CleanColumnName(profileProperty.PropertyName))

                                            Dim localUserId As Integer = CInt(dv(z).Item(effority.UserDirectory.Consts.USERID_COLUMN))

                                            If MaxLengthDic.TryGetValue(profileProperty.PropertyDefinitionId, Nothing) Then

                                                Dim maxLength As Int32 = MaxLengthDic(profileProperty.PropertyDefinitionId)

                                                If maxLength > 0 Then

                                                    If value.Length > maxLength Then

                                                        value = value.Substring(0, maxLength)

                                                    End If

                                                End If

                                            End If

                                            Select Case mode

                                                Case effority.UserDirectory.Enums.RenderMode.ProfileLink
                                                    sb.Append("<td nowrap class='" & CssBody & "'><a href='" & DotNetNuke.Common.Globals.LinkClick("UserID=" & localUserId, Me.TabId, Me.ModuleId) & "' target='_self'>" & value & "</a></td>")

                                                Case effority.UserDirectory.Enums.RenderMode.EmailMailTo
                                                    sb.Append(String.Format("<td nowrap class='{0}'><a href='mailto:{1}'>{1}</a></td>", CssBody, value))

                                                Case effority.UserDirectory.Enums.RenderMode.Text
                                                    sb.Append(String.Format("<td nowrap class='{0}'>{1}</td>", CssBody, value))

                                                Case Enums.RenderMode.vCardLink
                                                    sb.Append("<td nowrap class='" & CssBody & "'><a href='" & Me.GetvCardLink(localUserId) & "' target='_self'>" & value & "</a></td>")

                                                Case Enums.RenderMode.detailsView
                                                    sb.Append("<td nowrap class='" & CssBody & "'><a href='" & Me.GetDetailsViewLink(localUserId, searchText.Text) & "' target='_self'>" & value & "</a></td>")

                                                Case Enums.RenderMode.tabLink

                                                    Dim localTabId As Int32 = 0

                                                    If Integer.TryParse(value, localTabId) AndAlso TabDictionary.TryGetValue(localTabId, Nothing) Then

                                                        Dim tabInf As Entities.Tabs.TabInfo = TabDictionary(localTabId)

                                                        sb.Append("<td nowrap class='" & CssBody & "'><a href='" & NavigateURL(localTabId) & "' target='" & Me.TabLinkTarget & "'>" & tabInf.TabName & "</a></td>")

                                                    Else

                                                        sb.Append("<td></td>")

                                                    End If

                                            End Select

                                        Next

                                        sb.Append("</tr>")

                                    ElseIf Me.DisplayMode = Enums.DisplayMode.Template Then

                                        Dim info As New effority.UserDirectory.DetailInfo(dv(z))

                                        info.RenderMode = Enums.ReplaceEngineRenderMode.Grid

                                        info.Base = Me

                                        sb.Append(info.Replace(Me.DisplayTemplate))

                                    End If

                                End If

                            Next

                        End If

                    Next

                    sb.Append("</table>")

                    If pages > 1 Then

                        Dim st As String

                        For i As Int32 = 1 To pages

                            If i = selPage Then
                                st = String.Format("<a href='javascript:void(0)' class='NormalBold' onclick=""SendToUD('{0}')"">{0}</a>&nbsp;", CStr(i))
                            Else
                                st = String.Format("<a href='javascript:void(0)' class='Normal' onclick=""SendToUD('{0}')"">{0}</a>&nbsp;", CStr(i))
                            End If

                            sb.Append(st)

                        Next

                    End If

                    Return sb.ToString()

                End If

            Catch ex As Exception

                Return ex.ToString()

            End Try

        End Function

        Private Function BuildHtmlTableSearchBot(ByVal dv As DataView) As String

            Try

                Dim sb As New System.Text.StringBuilder

                If dv Is Nothing OrElse dv.Count = 0 Then

                    Return Me.HtmlNoResults

                Else

                    sb.Append("<table><tr>")

                    For Each profileProperty As DotNetNuke.Entities.Profile.ProfilePropertyDefinition In Me.ProfilesPropertyCollectionToShow

                        sb.Append(String.Format("<td>{0}</td>", profileProperty.PropertyName))

                    Next

                    sb.Append("</tr>")

                    For z As Integer = 0 To dv.Count - 1

                        sb.Append("<tr>")

                        For Each profileProperty As DotNetNuke.Entities.Profile.ProfilePropertyDefinition In Me.ProfilesPropertyCollectionToShow

                            sb.Append(String.Format("<td>{0}</td>", dv(z).Item(CleanColumnName(profileProperty.PropertyName))))

                        Next

                        sb.Append("</tr>")

                    Next

                End If

                sb.Append("</table>")

                Return sb.ToString()

            Catch ex As Exception

                'Return ex.ToString()

            Finally



            End Try

        End Function

#End Region

    End Class

End Namespace
